#pragma once
#include <map>
#include <string>
#include <vector>
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
#include <Types.h>
#include <Defines.h>
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
class MatrixProperties {
public:
   U64 m;
   U64 n;
   U64 nnz;
   U64 unz;
   U32 deg;
   U64 numNodes;
   U64 numDags;
   U64 numExplicitZeros;
   std::vector< U64 > rootNodeIdxs;
   std::vector< U64 > dagHgts;
   std::string rawFileName;
   std::string fullFileName;

   U64 nnzOffDiag;
   U64 unzOffDiag;
   U64 diagNonZeros;
   U64 storedNonZeros;
   std::string element_type;
   std::string symmetry_type;
   std::string matrix_type;
   bool isSymmetric;
   bool isSkewSymmetric;
   bool isComplex;
   bool isReal;
   bool isInteger;
   bool isPattern;

   MatrixProperties() {
      m = 0ULL;
      n = 0ULL;
      nnz = 0ULL;
      unz = 0ULL;
      deg = 0;
      numNodes = 0ULL;
      numDags = 0ULL;
      nnzOffDiag = 0ULL;
      unzOffDiag = 0ULL;
      diagNonZeros = 0ULL;
      storedNonZeros = 0ULL;
   }
};
class Coordinate {
public:
   U64 row;
   U64 col;
   inline bool operator==( const Coordinate & c ) const {
      if( row == c.row && col == c.col ) return true;
      return false;
   }
   inline bool operator <( const Coordinate & c ) const {
      if ( row == c.row )
         return col < c.col;
      return row < c.row;
   };
   Coordinate() {}
   Coordinate(const U64 r, const U64 c) : row(r), col(c) {}
   inline void Swap() {
      U64 buff = row;
      row = col;
      col = buff;
   }
};
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
U64 XtoTheN( const U64 x, U64 n );
U64 Log2Ceil( U64 v );
U64 LogXCeil( U64 v, U64 base );
U64 RoundUpToPow2( U64 v );
U64 RoundUpToPowX( U64 v, U64 base );
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
U64 Pos2RowRMA( U64 pos, U64 m, U64 n );
U64 Pos2ColRMA( U64 pos, U64 m, U64 n );
U32 Pos2RowQTS( const U64 _pos, const U32 _m, const U32 _n );
U32 Pos2ColQTS( const U64 _pos, const U32 _m, const U32 _n );
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
U64 RC2PosQTSInner( U64 r, U64 c, U64 m, U64 p, bool bd, bool ad );
U64 RC2PosQTS( U64 r, U64 c, U64 m, U64 n );
U64 RC2PosPSA( U64 r, U64 c, U64 m, U64 n );
U64 RC2Pos( U64 r, U64 c, U64 m, U64 n, const std::string & fmt );
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void PrintMappedMatrixToFile( const std::map< Coordinate, double > & mtx, const MatrixProperties & mtxMetaData, const std::string & filename );
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void SetThreadAffinity( const U32 tidx );
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
